package com.interview.rtc.aigc.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.ContentCachingResponseWrapper;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * 请求和响应日志记录拦截器
 */
@Component
public class LoggingInterceptor implements HandlerInterceptor {

    private static final Logger logger = LoggerFactory.getLogger(LoggingInterceptor.class);
    private static final ObjectMapper objectMapper = new ObjectMapper();
    private static final String REQUEST_START_TIME = "requestStartTime";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 记录请求开始时间
        request.setAttribute(REQUEST_START_TIME, System.currentTimeMillis());
        
        // 记录请求信息
        String requestURI = request.getRequestURI();
        String method = request.getMethod();
        String remoteAddr = request.getRemoteAddr();
        
        // 获取所有请求参数
        Map<String, String> requestParams = getRequestParameters(request);
        
        // 获取请求体
        String requestBody = "";
        if (request instanceof ContentCachingRequestWrapper) {
            ContentCachingRequestWrapper wrapper = (ContentCachingRequestWrapper) request;
            if (wrapper.getContentAsByteArray().length > 0) {
                requestBody = new String(wrapper.getContentAsByteArray());
            }
        }
        
        // 打印请求日志
        logger.info(">>>>>> Request: {} {} from IP: {}", method, requestURI, remoteAddr);
        logger.info(">>>>>> Parameters: {}", objectMapper.writeValueAsString(requestParams));
        if (!requestBody.isEmpty()) {
            logger.info(">>>>>> Request Body: {}", requestBody);
        }
        
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 在请求处理结束后、视图渲染前执行
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 计算请求处理时间
        Long startTime = (Long) request.getAttribute(REQUEST_START_TIME);
        long endTime = System.currentTimeMillis();
        long processingTime = endTime - startTime;
        
        // 记录响应信息
        String responseBody = "";
        if (response instanceof ContentCachingResponseWrapper) {
            ContentCachingResponseWrapper wrapper = (ContentCachingResponseWrapper) response;
            if (wrapper.getContentAsByteArray().length > 0) {
                responseBody = new String(wrapper.getContentAsByteArray());
                wrapper.copyBodyToResponse(); // 必须复制回去，否则客户端收不到响应
            }
        }
        
        // 打印响应日志
        logger.info("<<<<<< Response: {} - {} - {}ms", request.getRequestURI(), response.getStatus(), processingTime);
        if (!responseBody.isEmpty() && responseBody.length() < 1000) { // 避免响应体过大导致日志过大
            logger.info("<<<<<< Response Body: {}", responseBody);
        } else if (!responseBody.isEmpty()) {
            logger.info("<<<<<< Response Body too large, length: {}", responseBody.length());
        }
        
        // 如果有异常，记录异常信息
        if (ex != null) {
            logger.error("<<<<<< Exception: ", ex);
        }
    }

    /**
     * 获取所有请求参数
     */
    private Map<String, String> getRequestParameters(HttpServletRequest request) {
        Map<String, String> parameters = new HashMap<>();
        Enumeration<String> paramNames = request.getParameterNames();
        
        while (paramNames.hasMoreElements()) {
            String paramName = paramNames.nextElement();
            String paramValue = request.getParameter(paramName);
            parameters.put(paramName, paramValue);
        }
        
        return parameters;
    }
} 